package com.example.mysql.mybaits;

import org.apache.ibatis.jdbc.SQL;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ZhenWuWang
 */
@Component
public class BaseSqlProvider implements SqlProvider
{
    @Override
    public String insertBatch(Map<String, ?> map)
    {
        List<?> data = (List<?>) map.get("list");
        String tableName = (String) map.get("tableName");
        if (data == null || StringUtils.isEmpty(tableName))
            return null;

        data = data.stream().filter(Objects::nonNull).collect(Collectors.toList());
        if (data.isEmpty())
            return null;

        Object o = data.get(0);
        Class clazz = o.getClass();
        Map<String, List<String>> listMap = getFiledInfoList(clazz);
        List<String> filedNames = listMap.get("filedName");
        List<String> colNames = listMap.get("colNames");

        if (filedNames.isEmpty())
            return null;

        String valuesString = valuesString(filedNames);
        if (StringUtils.isEmpty(valuesString))
            return null;


        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder
                .append("INSERT INTO ")
                .append(tableName)
                .append(" (")
                .append(String.join(",", colNames))
                .append(") ")
                .append(" VALUES ");

        MessageFormat messageFormat = new MessageFormat(valuesString);
        for (int i = 0; i < data.size(); i++)
        {
            stringBuilder.append(messageFormat.format(new Object[]{i + ""}));
            if (i < data.size() - 1)
                stringBuilder.append(",");
        }
        return stringBuilder.toString();
    }

    private Map<String, List<String>> getFiledInfoList(Class clazz)
    {
        Map<String, List<String>> map = new HashMap<>();
        List<String> filedNames = new ArrayList<>();
        List<String> colNames = new ArrayList<>();
        map.put("filedName", filedNames);
        map.put("colNames", colNames);

        Field[] fields = clazz.getDeclaredFields();
        if (fields == null || fields.length == 0)
            return map;

        for (Field field : fields)
        {
            boolean fieldHasAnno = field.isAnnotationPresent(Column.class);
            if (fieldHasAnno)
            {
                Column column = field.getAnnotation(Column.class);
                String colName = column.name();
                if (StringUtils.isEmpty(colName))
                    continue;
                colNames.add(colName);
                filedNames.add(field.getName());
            }
        }
        return map;
    }

    @Override
    public String insert(Map<String, Object> map)
    {
        Object data = map.get("data");
        if (data == null)
            return null;
        map.put("list", Collections.singletonList(data));
        return insertBatch(map);
    }

    @Override
    public String deleteAll(String tableName)
    {
        SQL sql = new SQL().DELETE_FROM("`" + tableName + "`");
        return sql.toString();
    }

    @Override
    public String deleteByIds(Map<String, Object> map)
    {
        List<?> ids = (List<?>) map.get("list");
        String tableName = (String) map.get("tableName");
        SQL sql = new SQL().DELETE_FROM("`" + tableName + "`");
        sql.AND().WHERE("id in (" + String.join(",",
                ids.stream().map(o -> "'" + o.toString() + "'").collect(Collectors.toList())) + ")");
        return sql.toString();
    }

    @Override
    public String deleteByWhereCase(Map<String, Object> map)
    {
        String tableName = (String) map.get("tableName");
        SQL sql = new SQL().DELETE_FROM("`" + tableName + "`");

        String whereCase = null;
        if (map.containsKey("whereCase"))
        {
            Object o2 = map.get("whereCase");
            if (o2 != null)
                whereCase = (String) o2;
        }

        if (!StringUtils.isEmpty(whereCase))
        {
            sql.AND().WHERE(whereCase);
        }
//        LoggerUtil.info("select sql: " + sql.toString());
        return sql.toString();
    }

    @Override
    public String selectAll(String tableName)
    {
        SQL sql = new SQL().SELECT("*").FROM("`" + tableName + "`");
        return sql.toString();
    }

    /**
     * 返回select sql语句
     *
     * @param map 包含Key:columns和Key:whereCase
     *            key:columns的value为一个List<String>,list为需要查询的列名称 如果list为空则默认为*
     *            Key:whereCase的value为一个String 条件语句
     *            key:whereCaseValue的value为一个Object数值
     * @return 返回sql语句
     */
    @Override
    public String select(Map<String, Object> map)
    {
        String tableName = (String) map.get("tableName");

        List<String> columns = null;
        if (map.containsKey("columns"))
        {
            Object o = map.get("columns");
            if (o != null)
                columns = (List<String>) o;
        }

//        Object[] objects = null;
//        if (map.containsKey("whereCaseValue"))
//        {
//            Object o1 = map.get("whereCaseValue");
//            if (o1 != null)
//                objects = (Object[]) o1;
//        }

        String whereCase = null;
        if (map.containsKey("whereCase"))
        {
            Object o2 = map.get("whereCase");
            if (o2 != null)
                whereCase = (String) o2;
        }
//        if (!StringUtils.isEmpty(whereCase))
//        {
//            whereCase = whereCase.replaceAll("\\?", "%s");
//        }

        String colStr = "*";
        if (columns != null && !columns.isEmpty())
            colStr = String.join(",", columns);
        SQL sql = new SQL().SELECT(colStr).FROM(tableName);
        if (!StringUtils.isEmpty(whereCase))
        {
            sql.AND().WHERE(whereCase);
        }
//        LoggerUtil.info("select sql: " + sql.toString());
        return sql.toString();
    }

    @Override
    public String update(Map<String, Object> map)
    {
        return null;
    }

//    private List<String> getFileName(Class clazz)
//    {
//        Field[] fields = clazz.getDeclaredFields();
//
//        if (fields == null || fields.length == 0)
//            return Collections.emptyList();
//
//        return Stream
//                .of(fields)
//                .map(Field::getName)
//                .collect(Collectors.toList());
//    }

    private String valuesString(List<String> filedNames)
    {
        if (filedNames == null || filedNames.isEmpty())
            return "";
        StringBuilder stringBuilder = new StringBuilder("(");
        List<String> strings = filedNames
                .stream()
                .map(filedName -> "#'{'list[{0}]." + filedName + "}")
                .collect(Collectors.toList());
        String s = String.join(",", strings);
        stringBuilder.append(s);
        stringBuilder.append(")");
        return stringBuilder.toString();
    }
}
